package com.omybug.study.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.omybug.study.entity.JsonResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * User: omybug
 * Desc:
 * Date: 18/8/2 11:18
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Autowired
    private HttpServletRequest request;

    @ExceptionHandler(value = Exception.class)
    public Object exceptionHandle(Exception e) {
        this.logException(e);
        return JsonResponse.fail(-10, e.getMessage());
    }

    /**
     * 校验处理
     */
    @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
    public Object bindExceptionHandle(Exception e) {
        this.logException(e);
        BindingResult result = null;
        if (e instanceof BindException) {
            result = ((BindException) e).getBindingResult();
        }
        if (e instanceof MethodArgumentNotValidException) {
            result = ((MethodArgumentNotValidException) e).getBindingResult();
        }
        FieldError error = result.getFieldError();
        String field = error.getField();
        String code = error.getDefaultMessage();
        String message = String.format("%s:%s", field, code);
        return JsonResponse.fail(-1, message);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Object constraintViolationExceptionHandle(ConstraintViolationException e) {
        this.logException(e);
        log.error("参数验证失败", e);
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        ConstraintViolation<?> violation = violations.iterator().next();
        String message = violation.getMessage();
        return JsonResponse.fail(-1, message);
    }


    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Object httpRequestMethodNotSupportedExceptionHandle(HttpRequestMethodNotSupportedException e) {
        this.logException(e);
        return JsonResponse.fail(-1, "接口不支持该请求方式！");
    }

    /**
     * 缺少参数异常处理
     */
    @ExceptionHandler(value = {MissingServletRequestParameterException.class})
    public Object missingServletRequestParameterException(Exception e) {
        this.logException(e);
        return JsonResponse.fail(-1, e.getMessage());
    }

    private void logException(Exception e) {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, String[]> requestParameterMap = request.getParameterMap();
        HashMap<String, Object> data = new HashMap<>();
        data.put("url", request.getRequestURL());
        data.put("method", request.getMethod());
        try {
            data.put("data",objectMapper.writeValueAsString(requestParameterMap));
        } catch (JsonProcessingException jpe) {
            log.error(jpe.getMessage(),jpe);
        }
        log.error(data.toString(), e);
    }

    @ExceptionHandler(value = {IllegalArgumentException.class})
    public Object illegalArgumentException(Exception e)
    {
        return JsonResponse.fail(-1, e.getMessage());
    }

}
